package com.ruoyi.ca.service.impl;

import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.ruoyi.ca.domain.CaJylsh;
import com.ruoyi.ca.service.ICaJylshService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.ruoyi.ca.mapper.CaFpxxMapper;
import com.ruoyi.ca.domain.CaFpxx;
import com.ruoyi.ca.service.ICaFpxxService;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

/**
 * 发票信息Service业务层处理
 *
 * @author ycong
 * @date 2024-04-13
 */
@Service
public class CaFpxxServiceImpl implements ICaFpxxService {

    @Value("${fp.path}")
    private String fpPath;
    ;

    @Autowired
    private CaFpxxMapper caFpxxMapper;

    @Resource
    private ICaJylshService caJylshService;

    /**
     * 查询发票信息
     *
     * @param id 发票信息主键
     * @return 发票信息
     */
    @Override
    public CaFpxx selectCaFpxxById(Long id) {
        return caFpxxMapper.selectCaFpxxById(id);
    }

    /**
     * 查询发票信息列表
     *
     * @param caFpxx 发票信息
     * @return 发票信息
     */
    @Override
    public List<CaFpxx> selectCaFpxxList(CaFpxx caFpxx) {
        return caFpxxMapper.selectCaFpxxList(caFpxx);
    }

    /**
     * 新增发票信息
     *
     * @param caFpxx 发票信息
     * @return 结果
     */
    @Override
    public int insertCaFpxx(CaFpxx caFpxx) {
        caFpxx.setCreateTime(DateUtils.getNowDate());
        return caFpxxMapper.insertCaFpxx(caFpxx);
    }

    /**
     * 修改发票信息
     *
     * @param caFpxx 发票信息
     * @return 结果
     */
    @Override
    public int updateCaFpxx(CaFpxx caFpxx) {
        caFpxx.setUpdateTime(DateUtils.getNowDate());
        return caFpxxMapper.updateCaFpxx(caFpxx);
    }

    /**
     * 批量删除发票信息
     *
     * @param ids 需要删除的发票信息主键
     * @return 结果
     */
    @Override
    public int deleteCaFpxxByIds(Long[] ids) {
        return caFpxxMapper.deleteCaFpxxByIds(ids);
    }

    /**
     * 删除发票信息信息
     *
     * @param id 发票信息主键
     * @return 结果
     */
    @Override
    public int deleteCaFpxxById(Long id) {
        return caFpxxMapper.deleteCaFpxxById(id);
    }

    /**
     * 发票数据导入
     *
     * @param dataPackage
     * @param operName
     * @return
     */
    @Override
    public String importCaFpxx(MultipartFile dataPackage, String operName) {
        if (dataPackage == null || dataPackage.getSize() <= 0) {
            return null;
        }
        File file = multipartFileToFile(dataPackage);
        if (file == null || !file.exists()) {
            return null;
        }
        ZipFile zipFile = null;
        try {
            zipFile = new ZipFile(file, Charset.forName("GBK"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        Enumeration<? extends ZipEntry> dirEntries = zipFile.entries();
        while (dirEntries.hasMoreElements()) {
            ZipEntry entry = dirEntries.nextElement();
            if (entry.isDirectory()) {
                continue;
            }
            String fileName = entry.getName();
            if (endsWithIgnoreCase(fileName, ".pdf") || endsWithIgnoreCase(fileName, ".ofd") || endsWithIgnoreCase(fileName, ".xml")) {
                String[] fileNameArray = fileName.split("_");
                String fphm = fileNameArray[1];     // 发票号码
                String gfmc = fileNameArray[2];     // 供方名称

                CaFpxx caFpxx = caFpxxMapper.queryByFphm(fphm);


                // 获取节点输入流
                try {
                    InputStream inputStream = zipFile.getInputStream(entry);

                    try (OutputStream outputStream = new BufferedOutputStream(Files.newOutputStream(Paths.get(fpPath + fileName)))) {
                        byte[] buffer = new byte[8192]; // 缓冲区大小为8KB

                        int bytesRead;
                        while ((bytesRead = inputStream.read(buffer)) != -1) {
                            outputStream.write(buffer, 0, bytesRead);
                        }
                    }
                    // 发票号码不存在
                    if (caFpxx == null) {
                        CaFpxx fpxx = new CaFpxx();
                        Snowflake snowflake = IdUtil.createSnowflake(1, 1);
                        long id = snowflake.nextId();
                        fpxx.setId(id);
                        fpxx.setFphm(fphm);
                        fpxx.setGfmc(gfmc);
                        fpxx.setFjmc(fileName.substring(0, fileName.lastIndexOf(".")));
                        fpxx.setCreateTime(DateUtils.getNowDate());
                        fpxx.setCreateBy(operName);
                        this.insertCaFpxx(fpxx);
                    }


                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                // 获取节点元数据
                System.out.println(fileName);
            }
        }
        // 回收资源
        IOUtils.closeQuietly(zipFile);
        file.delete();
        return "发票上传成功！";
    }

    /**
     * 发票下载
     *
     * @param fileName
     * @param response
     */
    @Override
    public void downLoad(String fileName, HttpServletResponse response) {
        try {
            // path是指欲下载的文件的路径。
            File file = new File(fpPath + fileName);

            // 以流的形式下载文件。
            InputStream fis = new BufferedInputStream(Files.newInputStream(file.toPath()));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            String encodedFileName = URLEncoder.encode(fileName, "UTF-8");            // 设置response的Header
            response.addHeader("Content-Disposition", "attachment;filename=" + encodedFileName);
            response.addHeader("Content-Length", "" + file.length());
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
        } catch (IOException ex) {
            throw new ServiceException(ex.getMessage());
        }
    }

    /**
     * 查询供方名称
     * @param gfmc
     * @return
     */
    @Override
    public List<String> queryGfmc(String gfmc) {
        return caFpxxMapper.queryGfmc(gfmc);
    }

    /**
     * 根据交易流水号查询发票信息
     * @param jylsh
     * @return
     */
    @Override
    public List<CaFpxx> queryFpxxListByJylsh(String jylsh) {

//        CaJylsh caJylsh = caJylshService.selectByJylsh(jylsh);

        return caFpxxMapper.queryFpxxListByJylsh(jylsh);
    }

    /**
     * MultipartFile 转 File
     *
     * @param multipartFile
     * @return
     */
    private File multipartFileToFile(MultipartFile multipartFile) {
        File file = null;
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            inputStream = multipartFile.getInputStream();
            file = new File(multipartFile.getOriginalFilename());
            outputStream = new FileOutputStream(file);
            write(inputStream, outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return file;
    }

    public void write(InputStream inputStream, OutputStream outputStream) {
        byte[] buffer = new byte[4096];
        try {
            int count = inputStream.read(buffer, 0, buffer.length);
            while (count != -1) {
                outputStream.write(buffer, 0, count);
                count = inputStream.read(buffer, 0, buffer.length);
            }
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public static boolean endsWithIgnoreCase(String str, String suffix) {
        int suffixLength = suffix.length();
        return str.regionMatches(true, str.length() - suffixLength, suffix, 0, suffixLength);
    }
}
